package com.zouxw.utils.json.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Schema管理工具类
 * 提供Schema的存储、加载、管理功能
 * 
 * @author zouxw
 * @version 1.0.0
 */
public class SchemaManager {
    
    private static final String SCHEMA_DIR = "schemas";
    private static final String SCHEMA_EXTENSION = ".schema.json";
    private static final String SCHEMA_INDEX_FILE = "schema_index.json";
    
    private final Map<String, String> schemaCache = new ConcurrentHashMap<>();
    private final Map<String, SchemaInfo> schemaInfoCache = new ConcurrentHashMap<>();
    
    /**
     * Schema信息类
     */
    public static class SchemaInfo {
        private String name;
        private String description;
        private String version;
        private String author;
        private long createTime;
        private long lastModified;
        private String fileName;
        private String content;
        
        public SchemaInfo() {
            this.createTime = System.currentTimeMillis();
            this.lastModified = System.currentTimeMillis();
        }
        
        public SchemaInfo(String name, String description, String content) {
            this();
            this.name = name;
            this.description = description;
            this.content = content;
        }
        
        // Getters and Setters
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        
        public String getVersion() { return version; }
        public void setVersion(String version) { this.version = version; }
        
        public String getAuthor() { return author; }
        public void setAuthor(String author) { this.author = author; }
        
        public long getCreateTime() { return createTime; }
        public void setCreateTime(long createTime) { this.createTime = createTime; }
        
        public long getLastModified() { return lastModified; }
        public void setLastModified(long lastModified) { this.lastModified = lastModified; }
        
        public String getFileName() { return fileName; }
        public void setFileName(String fileName) { this.fileName = fileName; }
        
        public String getContent() { return content; }
        public void setContent(String content) { 
            this.content = content;
            this.lastModified = System.currentTimeMillis();
        }
        
        @Override
        public String toString() {
            return String.format("SchemaInfo{name='%s', description='%s', version='%s', author='%s'}", 
                name, description, version, author);
        }
    }
    
    /**
     * 构造函数
     */
    public SchemaManager() {
        initializeSchemaDirectory();
        loadSchemaIndex();
    }
    
    /**
     * 初始化Schema目录
     */
    private void initializeSchemaDirectory() {
        File schemaDir = new File(SCHEMA_DIR);
        if (!schemaDir.exists()) {
            schemaDir.mkdirs();
        }
    }
    
    /**
     * 加载Schema索引
     */
    private void loadSchemaIndex() {
        File indexFile = new File(SCHEMA_DIR, SCHEMA_INDEX_FILE);
        if (indexFile.exists()) {
            try (InputStreamReader reader = new InputStreamReader(new FileInputStream(indexFile), StandardCharsets.UTF_8)) {
                String content = readFileContent(reader);
                JSONObject indexJson = JSON.parseObject(content);
                
                for (String key : indexJson.keySet()) {
                    JSONObject schemaJson = indexJson.getJSONObject(key);
                    SchemaInfo info = new SchemaInfo();
                    info.setName(schemaJson.getString("name"));
                    info.setDescription(schemaJson.getString("description"));
                    info.setVersion(schemaJson.getString("version"));
                    info.setAuthor(schemaJson.getString("author"));
                    info.setCreateTime(schemaJson.getLongValue("createTime"));
                    info.setLastModified(schemaJson.getLongValue("lastModified"));
                    info.setFileName(schemaJson.getString("fileName"));
                    
                    schemaInfoCache.put(key, info);
                }
            } catch (Exception e) {
                System.err.println("加载Schema索引失败: " + e.getMessage());
            }
        }
    }
    
    /**
     * 保存Schema索引
     */
    private void saveSchemaIndex() {
        File indexFile = new File(SCHEMA_DIR, SCHEMA_INDEX_FILE);
        try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(indexFile), StandardCharsets.UTF_8)) {
            JSONObject indexJson = new JSONObject();
            
            for (Map.Entry<String, SchemaInfo> entry : schemaInfoCache.entrySet()) {
                SchemaInfo info = entry.getValue();
                JSONObject schemaJson = new JSONObject();
                schemaJson.put("name", info.getName());
                schemaJson.put("description", info.getDescription());
                schemaJson.put("version", info.getVersion());
                schemaJson.put("author", info.getAuthor());
                schemaJson.put("createTime", info.getCreateTime());
                schemaJson.put("lastModified", info.getLastModified());
                schemaJson.put("fileName", info.getFileName());
                
                indexJson.put(entry.getKey(), schemaJson);
            }
            
            writer.write(JSON.toJSONString(indexJson, true));
        } catch (Exception e) {
            System.err.println("保存Schema索引失败: " + e.getMessage());
        }
    }
    
    /**
     * 保存Schema
     * 
     * @param name Schema名称
     * @param description Schema描述
     * @param content Schema内容
     * @param author 作者
     * @return 是否保存成功
     */
    public boolean saveSchema(String name, String description, String content, String author) {
        try {
            // 验证Schema格式
            if (!JsonSchemaValidator.isValidSchema(content)) {
                throw new IllegalArgumentException("Schema格式无效");
            }
            
            // 创建Schema信息
            SchemaInfo info = new SchemaInfo(name, description, content);
            info.setAuthor(author);
            info.setVersion("1.0.0");
            
            // 生成文件名
            String fileName = generateFileName(name);
            info.setFileName(fileName);
            
            // 保存Schema文件
            File schemaFile = new File(SCHEMA_DIR, fileName);
            try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(schemaFile), StandardCharsets.UTF_8)) {
                writer.write(JsonSchemaValidator.formatSchema(content));
            }
            
            // 更新缓存
            schemaInfoCache.put(name, info);
            schemaCache.put(name, content);
            
            // 保存索引
            saveSchemaIndex();
            
            return true;
        } catch (Exception e) {
            System.err.println("保存Schema失败: " + e.getMessage());
            return false;
        }
    }
    
    /**
     * 加载Schema
     * 
     * @param name Schema名称
     * @return Schema内容，如果不存在则返回null
     */
    public String loadSchema(String name) {
        // 先从缓存获取
        if (schemaCache.containsKey(name)) {
            return schemaCache.get(name);
        }
        
        // 从文件加载
        SchemaInfo info = schemaInfoCache.get(name);
        if (info != null) {
            try {
                File schemaFile = new File(SCHEMA_DIR, info.getFileName());
                if (schemaFile.exists()) {
                    String content = readFileContent(new InputStreamReader(new FileInputStream(schemaFile), StandardCharsets.UTF_8));
                    schemaCache.put(name, content);
                    return content;
                }
            } catch (Exception e) {
                System.err.println("加载Schema失败: " + e.getMessage());
            }
        }
        
        return null;
    }
    
    /**
     * 删除Schema
     * 
     * @param name Schema名称
     * @return 是否删除成功
     */
    public boolean deleteSchema(String name) {
        try {
            SchemaInfo info = schemaInfoCache.get(name);
            if (info != null) {
                // 删除文件
                File schemaFile = new File(SCHEMA_DIR, info.getFileName());
                if (schemaFile.exists()) {
                    schemaFile.delete();
                }
                
                // 从缓存移除
                schemaInfoCache.remove(name);
                schemaCache.remove(name);
                
                // 保存索引
                saveSchemaIndex();
                
                return true;
            }
        } catch (Exception e) {
            System.err.println("删除Schema失败: " + e.getMessage());
        }
        
        return false;
    }
    
    /**
     * 获取所有Schema名称
     * 
     * @return Schema名称列表
     */
    public List<String> getAllSchemaNames() {
        return new ArrayList<>(schemaInfoCache.keySet());
    }
    
    /**
     * 获取Schema信息
     * 
     * @param name Schema名称
     * @return Schema信息，如果不存在则返回null
     */
    public SchemaInfo getSchemaInfo(String name) {
        return schemaInfoCache.get(name);
    }
    
    /**
     * 获取所有Schema信息
     * 
     * @return Schema信息列表
     */
    public List<SchemaInfo> getAllSchemaInfos() {
        return new ArrayList<>(schemaInfoCache.values());
    }
    
    /**
     * 检查Schema是否存在
     * 
     * @param name Schema名称
     * @return 是否存在
     */
    public boolean schemaExists(String name) {
        return schemaInfoCache.containsKey(name);
    }
    
    /**
     * 更新Schema
     * 
     * @param name Schema名称
     * @param content 新的Schema内容
     * @return 是否更新成功
     */
    public boolean updateSchema(String name, String content) {
        try {
            SchemaInfo info = schemaInfoCache.get(name);
            if (info != null) {
                // 验证Schema格式
                if (!JsonSchemaValidator.isValidSchema(content)) {
                    throw new IllegalArgumentException("Schema格式无效");
                }
                
                // 更新内容
                info.setContent(content);
                
                // 保存到文件
                File schemaFile = new File(SCHEMA_DIR, info.getFileName());
                try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(schemaFile), StandardCharsets.UTF_8)) {
                    writer.write(JsonSchemaValidator.formatSchema(content));
                }
                
                // 更新缓存
                schemaCache.put(name, content);
                
                // 保存索引
                saveSchemaIndex();
                
                return true;
            }
        } catch (Exception e) {
            System.err.println("更新Schema失败: " + e.getMessage());
        }
        
        return false;
    }
    
    /**
     * 生成文件名
     * 
     * @param name Schema名称
     * @return 文件名
     */
    private String generateFileName(String name) {
        // 替换非法字符
        String safeName = name.replaceAll("[^a-zA-Z0-9_-]", "_");
        return safeName + SCHEMA_EXTENSION;
    }
    
    /**
     * 读取文件内容
     * 
     * @param reader 文件读取器
     * @return 文件内容
     * @throws IOException IO异常
     */
    private String readFileContent(Reader reader) throws IOException {
        StringBuilder content = new StringBuilder();
        char[] buffer = new char[1024];
        int length;
        while ((length = reader.read(buffer)) != -1) {
            content.append(buffer, 0, length);
        }
        return content.toString();
    }
    
    /**
     * 清空缓存
     */
    public void clearCache() {
        schemaCache.clear();
    }
    
    /**
     * 重新加载所有Schema
     */
    public void reloadAllSchemas() {
        clearCache();
        loadSchemaIndex();
    }
    
    /**
     * 获取Schema目录路径
     * 
     * @return Schema目录路径
     */
    public String getSchemaDirectory() {
        return new File(SCHEMA_DIR).getAbsolutePath();
    }
}
